package com.cloudkinto.service.sc.impl;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.BeanConvert;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.ExcelUtils;
import com.cloudkinto.common.utils.StringsUtil;
import com.cloudkinto.common.utils.TimeUtils;
import com.cloudkinto.common.utils.ali.AliOss;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.ScFarawayInfoRuleDao;
import com.cloudkinto.dao.ScFarawayRuleDao;
import com.cloudkinto.entity.ScFarawayInfoRuleDo;
import com.cloudkinto.entity.ScFarawayRuleDo;
import com.cloudkinto.service.sc.ScFarawayInfoRuleService;
import com.cloudkinto.service.sc.ScFarawayRuleService;
import com.cloudkinto.service.zone.ZoneTempService;
import com.cloudkinto.vo.sc.ErrorInfo;
import com.cloudkinto.vo.sc.ScFarawayInfoPageVo;
import com.cloudkinto.vo.sc.ScFarawayPageVo;
import com.cloudkinto.vo.sc.faraway.*;
import com.cloudkinto.vo.sc.importVo.FarawayDetailExportVo;
import com.cloudkinto.vo.sc.importVo.ScFarawayDetailErrorExportVo;
import com.cloudkinto.vo.sc.importVo.ScFarawayDetailImportVo;
import com.cloudkinto.vo.sc.style.FarawayExportTitleStyle;
import com.cloudkinto.vo.zone.PostCodeRes;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 * 偏远地区规则 service实现类
 * </p>
 *
 * @author hua
 * @since 2024-11-05
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class ScFarawayRuleServiceImpl extends ServiceImpl<ScFarawayRuleDao, ScFarawayRuleDo> implements ScFarawayRuleService {
    @Autowired
    private ScFarawayRuleDao dao;
    @Autowired
    private ZoneTempService zoneTempService;
    @Autowired
    private ScFarawayInfoRuleDao scFarawayInfoRuleDao;
    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;
    @Value("${gbc.uploadPath.filePath}")
    private String filePath;
    @Value("${gbc.uploadPath.fileUrl}")
    private String fileUrl;
    @Autowired
    private ScFarawayInfoRuleService scFarawayInfoRuleService;

    @Override
    public SingleResult addInit() {
        return SingleResult.success("");
    }


    public void check(FarawayAddReq addReq, Long id, Long tenantId) {
        if (StringUtils.isBlank(addReq.getFarawayRuleName()))
            throw new BizException(SysConstant.ScFaraway_Add_Name_Empty);
        //名称不能重复
        ScFarawayRuleDo et = dao.selectOne(new LambdaQueryWrapper<ScFarawayRuleDo>()
                .ne(id != null, ScFarawayRuleDo::getId, id)
                .eq(ScFarawayRuleDo::getFarawayRuleName, addReq.getFarawayRuleName())
                .eq(ScFarawayRuleDo::getTenantId, tenantId));
        if (et != null) throw new BizException(SysConstant.ScFaraway_Add_Name_Same);
    }

    @Override
    public Object add(FarawayAddReq req, Long userId, Long tenantId) {
        this.check(req, null, tenantId);
        ScFarawayRuleDo entityDo = new ScFarawayRuleDo();
        BeanUtils.copyProperties(req, entityDo);
//        entityDo.setCreateBy(userId);
//        entityDo.setTenantId(tenantId);
        baseMapper.insert(entityDo);
        return entityDo.getId();
    }

    //新增校验
    private void addCheck(Object req) {

    }

    //做新增之前要执行的业务定制处理
    private void handlerAddBefore(ScFarawayRuleDo entityDo, Long userId) {
        entityDo.setCreateBy(userId);
        entityDo.setCreateTime(new Date());
        entityDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
    }

    //将新增的do转换成要返回的实体
    private Object handlerAddAfter(ScFarawayRuleDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public SingleResult updateInit(Long id) {
        return SingleResult.success("");
    }

    @Override
    public Object update(FarawayUpdateReq req, Long userId, Long tenantId) {
        this.check(req, req.getId(), tenantId);
        ScFarawayRuleDo entityDo = dao.selectById(req.getId());
        if (entityDo == null) throw new BizException(SysConstant.No_Data);
        BeanUtils.copyProperties(req, entityDo);
        dao.updateById(entityDo);
        return entityDo.getId();
    }


    @Override
    public int delete(Long id, Long userId, Long tenantId) {
        int count = dao.getUsedCount(id, tenantId);
        if (count > 0) throw new BizException(SysConstant.Rule_HadUsed);
        int i = dao.updateDelete(id, userId, tenantId);
        if (i > 0) {
            scFarawayInfoRuleDao.updateDeleteByFarId(id, userId);
        }
        return i;
    }


    @Override
    public Object detail(Long id) {
        ScFarawayRuleDo entityDo = dao.selectById(id);
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return handlerDetailAfter(res);
    }

    //查询明细之后要执行的业务定制处理
    private Object handlerDetailAfter(Object res) {
        return res;
    }

    @Override
    public SingleResult pageInit() {
        Map<String, Object> result = new HashMap<>();
        result.put("farawayType", StaticDict.geFarawayType());
        return SingleResult.success(result);
    }


    @Override
    public List<ScFarawayPageVo> getList(Map<String, Object> map) {
        List<ScFarawayPageVo> list = dao.list(map);
        return list;
    }

    @Override
    public PageResult getListPage(Map<String, Object> map) {
        IPage<ScFarawayPageVo> page = pageInitDto(map);
        page = dao.list(page, map);
        PageResult result = new PageResult(page.getRecords(), (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<Object> handlerListAfter(List<ScFarawayRuleDo> list) {
        List<Object> result = new ArrayList<>();
        return result;
    }

    private IPage<ScFarawayRuleDo> pageInit(Map<String, String> map) {
        IPage<ScFarawayRuleDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }


    private IPage<ScFarawayPageVo> pageInitDto(Map<String, Object> map) {
        IPage<ScFarawayPageVo> page = new Page();
        page.setSize(map.get("pageSize") != null ? Long.parseLong(map.get("pageSize").toString()) : 10);
        page.setCurrent(map.get("current") != null ? Long.parseLong(map.get("current").toString()) : 1);
        return page;
    }

    private QueryWrapper<ScFarawayRuleDo> queryBuild(Map<String, String> map) {
        QueryWrapper<ScFarawayRuleDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.like("keyword", map.get("keyword"));
        }
        return wrapper;
    }


    @Override
    public FarawayRuleImportRes importRuleDetail(MultipartFile file, Long farawayRuleId, Long userId, Long tenantId) {
        List<ScFarawayDetailImportVo> importVos = new ArrayList<>();
        try {
            importVos = ExcelUtils.importExcel(file, 1, 0, ScFarawayDetailImportVo.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        List<FarawayInfoRuleAddReq> successRuleList = new ArrayList<>();
        List<ScFarawayDetailErrorExportVo> errorExportVos = new ArrayList<>();
        List<ErrorInfo> errorList = new ArrayList<>();
        for (int i = 0; i < importVos.size(); i++) {
            ScFarawayDetailImportVo importVo = importVos.get(i);
            if (StringUtils.isBlank(importVo.getCountryCode()) && StringUtils.isBlank(importVo.getState()) &&
                    StringUtils.isBlank(importVo.getCity()) && StringUtils.isBlank(importVo.getStartPostcode()) && StringUtils.isBlank(importVo.getEndPostcode()))
                continue;
            List<String> errors = this.check(importVo.getCountryCode(), importVo.getStartPostcode(), importVo.getEndPostcode());
            if (errors.isEmpty()) {
                successRuleList.add(new FarawayInfoRuleAddReq(importVo.getCountryCode(), importVo.getState(), importVo.getCity(), importVo.getStartPostcode(), importVo.getEndPostcode(), null));
            } else {
                StringBuilder error = new StringBuilder();
                for (String s : errors) {
                    if (error.length() > 0) error.append(";");
                    error.append(StringsUtil.createI18Message(s));
                }
                errorList.add(new ErrorInfo((i + 1) + "", StringsUtil.createI18Message(error.toString())));
                errorExportVos.add(new ScFarawayDetailErrorExportVo(error.toString(), importVo.getCountryCode(), importVo.getState(), importVo.getCity(), importVo.getStartPostcode(), importVo.getEndPostcode()));
            }
        }
        if (!successRuleList.isEmpty()) {
            //删除之前的
            scFarawayInfoRuleDao.updateDeleteByFarId(farawayRuleId, userId);
        }
        for (FarawayInfoRuleAddReq farawayInfoRuleAddReq : successRuleList) {
            farawayInfoRuleAddReq.setFarawayRuleId(farawayRuleId);
            this.addInfoRule(farawayInfoRuleAddReq, userId, false);
        }
        FarawayRuleImportRes res = new FarawayRuleImportRes();
        res.setFailNum(errorExportVos.size());
        res.setSuccessNum(successRuleList.size());
        res.setSuccessList(successRuleList);
        if (errorExportVos.isEmpty()) return res;
        String fileName = "错误_偏远明细导入" + TimeUtils.getCurrentDateFormat("MMddHHmmss") + ".xlsx";

        try {
            ExcelUtils.exportExcelToSave(errorExportVos, ScFarawayDetailErrorExportVo.class, fileName, new ExportParams(), filePathTemp);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        String objectNameTemporary = "";
        if (filePath.startsWith("http")) {
            try {
                objectNameTemporary = AliOss.temporaryFile2(fileName, new File(filePathTemp + fileName));
            } catch (Exception e) {
                e.printStackTrace();
                log.error("导出文件失败" + e.getMessage());
            }
            res.setFailFileUrl(fileUrl + objectNameTemporary);
        } else {
            res.setFailFileUrl(fileUrl + fileName);
        }
        res.setFileName(fileName);
        res.setErrorList(errorList);
        return res;
    }

    public List<String> check(String countyCode, String startCode, String endCode) {
        List<String> errors = new ArrayList<>();
        if (StringUtils.isBlank(countyCode)) {
            errors.add(SysConstant.ScOverRule_Add_CountyCode_Empty);
        } else if (countyCode.length() > 2) {
            errors.add(SysConstant.ScOverRule_Add_CountyCode_Long);
        }
        if (StringUtils.isBlank(startCode)) errors.add(SysConstant.ScOverRule_Add_StartPostCode_Empty);
        if (StringUtils.isBlank(endCode)) errors.add(SysConstant.ScOverRule_Add_EndPostCode_Empty);
        if (StringUtils.isNotBlank(startCode) && StringUtils.isNotBlank(endCode)) {
            if (startCode.length() != endCode.length()) errors.add(SysConstant.PostCode_Length_Error);
        }
        PostCodeRes postCode = zoneTempService.getPostCode(startCode, endCode, zoneTempService.getZimuMap());
        if (postCode.getBegin() > postCode.getEnd()) errors.add(SysConstant.Post_Start_Bigger);
        return errors;
    }

    @Override
    public void exportDetailRule(String farawayRuleId, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<>();
        map.put("farawayRuleId", farawayRuleId);
        List<ScFarawayInfoPageVo> list = scFarawayInfoRuleDao.list(map);

        List<FarawayDetailExportVo> exportVos = BeanConvert.INSTANCE.farawayDetailExportVoList(list);

        String fileName = "偏远明细导出" + TimeUtils.getCurrentDateFormat("MMddHHmmss");

        ExportParams excelParam = new ExportParams();
        excelParam.setStyle(FarawayExportTitleStyle.class);
//        excelParam.setHeight((short) 10);
        excelParam.setTitleHeight((short) 20);
//        excelParam.setHeaderHeight(40D);
        try {
//            ExcelUtils.exportExcelToSave(exportVos, FarawayDetailExportVo.class, fileName+ ".xlsx", excelParam, filePathTemp);
            ExcelUtils.exportExcel(exportVos, FarawayDetailExportVo.class, fileName, excelParam, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


    }


    @Override
    public Object addInfoRule(FarawayInfoRuleAddReq req, Long userId, boolean check) {
        if (check) {
            List<String> errors = this.check(req.getCountryCode(), req.getStartPostcode(), req.getEndPostcode());
            if (!errors.isEmpty()) throw new BizException(errors.get(0));
        }
        ScFarawayInfoRuleDo entityDo = new ScFarawayInfoRuleDo();
        BeanUtils.copyProperties(req, entityDo);
//        entityDo.setCreateBy(userId);
        scFarawayInfoRuleDao.insert(entityDo);
        return null;
    }


    @Override
    public Object updateInfoRule(FarawayInfoRuleUpdateReq req, Long userId, boolean check) {
        if (check) {
            List<String> errors = this.check(req.getCountryCode(), req.getStartPostcode(), req.getEndPostcode());
            if (!errors.isEmpty()) throw new BizException(errors.get(0));
        }
        ScFarawayInfoRuleDo entityDo = scFarawayInfoRuleDao.selectById(req.getId());
        BeanUtils.copyProperties(req, entityDo);
        entityDo.setUpdateBy(userId);
        scFarawayInfoRuleDao.updateById(entityDo);
        return null;
    }


}
